package com.xcdh.orm.controller;

import com.xcdh.commons.utils.exception.AssertUtil;
import com.xcdh.domain.vo.R;
import com.xcdh.orm.config.DataSourceCache;
import com.xcdh.orm.ddl.DDLIndex;
import com.xcdh.orm.ddl.DDLPayload;
import com.xcdh.orm.ddl.DDLTable;
import com.xcdh.orm.entity.OrmDataSource;
import com.xcdh.orm.handler.DbServiceProxy;
import com.xcdh.orm.service.ddl.DDLColumnService;
import com.xcdh.orm.service.ddl.DDLDataBaseService;
import com.xcdh.orm.service.ddl.DDLIndexService;
import com.xcdh.orm.service.ddl.DDLTableService;
import com.xcdh.orm.util.DBServiceUtil;
import org.apache.ibatis.jdbc.ScriptRunner;
import org.apache.ibatis.parsing.GenericTokenParser;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.sql.DataSource;
import java.io.StringReader;
import java.util.List;

@RestController
@RequestMapping("/ddl")
public class DDLController {

    @Autowired
    private DataSourceCache dataSourceCache ;

    @PostMapping("/showTable/{serviceId}")
    public R showTable(@PathVariable String serviceId){
        return R.okData(DbServiceProxy.cretedDDLService(serviceId , DDLTableService.class).showTables()) ;
    }

    /**
     * 查询表
     * @param serviceId
     * @param table
     * @return
     */
    @PostMapping("/queryTable/{serviceId}")
    public R queryTable(@PathVariable String serviceId , @RequestBody DDLTable table){
        return R.okData(DbServiceProxy.cretedDDLService(serviceId , DDLTableService.class).queryTables(table)) ;
    }

    /**
     * 删除表
     * @param serviceId
     * @param table
     * @return
     */
    @PostMapping("/dropTable/{serviceId}")
    public R dropTable(@PathVariable String serviceId , @RequestBody DDLTable table){
        return R.okData(DbServiceProxy.cretedDDLService(serviceId , DDLTableService.class).dropTable(table)) ;
    }

    /**
     * 删除表
     * @param serviceId
     * @param tables
     * @return
     */
    @PostMapping("/dropTableBatch/{serviceId}")
    public R dropTableBatch(@PathVariable String serviceId , @RequestBody List<DDLTable> tables){
        for (DDLTable ddlTable : tables) {
            DbServiceProxy.cretedDDLService(serviceId , DDLTableService.class).dropTable(ddlTable) ;
        }
        return R.ok() ;
    }

    /**
     * 查询索引
     * @param serviceId
     * @param index
     * @return
     */
    @PostMapping("/queryIndex/{serviceId}")
    public R queryIndex(@PathVariable String serviceId , @RequestBody DDLIndex index){
        return R.okData(DbServiceProxy.cretedDDLService(serviceId , DDLIndexService.class).queryIndex(index)) ;
    }

    /**
     * 删除索引
     * @param serviceId
     * @param index
     * @return
     */
    @PostMapping("/dropIndex/{serviceId}")
    public R dropIndex(@PathVariable String serviceId , @RequestBody DDLIndex index){
        return R.okData(DbServiceProxy.cretedDDLService(serviceId , DDLIndexService.class).dropIndex(index)) ;
    }

    /**
     * 查询字段
     * @param serviceId
     * @param table
     * @return
     */
    @PostMapping("/getTableColumns/{serviceId}")
    public R getTableColumns(@PathVariable String serviceId , @RequestBody DDLTable table){
        return R.okData(DbServiceProxy.cretedDDLService(serviceId , DDLColumnService.class).getTableColumns(table)) ;
    }

    @PostMapping("/showDataBases/{serviceId}")
    public R showDataBasesV2(@PathVariable String serviceId){
        return R.okData(DbServiceProxy.cretedDDLService(serviceId , DDLDataBaseService.class).showDataBases()) ;
    }


    /**
     * 根据现有的表创建表
     * @param serviceId
     * @param payload
     * @return
     */
    @PostMapping("/copyTable/{serviceId}")
    public R copyTable(@PathVariable String serviceId , @RequestBody DDLPayload payload){
        for (String database : payload.getDatabases()) {
            DDLTable table = new DDLTable() ;
            BeanUtils.copyProperties(payload.getTable() ,table );
            table.setDataBaseName(database);
            for (DDLIndex index : table.getIdxList()) {
                index.setTableName(table.getNewTableName());
                index.setDataBaseName(database);
            }
            DbServiceProxy.cretedDDLService(serviceId , DDLTableService.class).copyTable(table) ;
            DbServiceProxy.cretedDDLService(serviceId , DDLIndexService.class).createIndex(table.getIdxList()) ;
        }
        return R.ok() ;
    }

    /**
     * 创建索引
     * @param serviceId
     * @param indexList
     * @return
     */
    @PostMapping("/createdIndex/{serviceId}")
    private R createIndex(@PathVariable String serviceId , @RequestBody List<DDLIndex> indexList){
        DbServiceProxy.cretedDDLService(serviceId , DDLIndexService.class).createIndex(indexList) ;
        return R.ok() ;
    }

    @PostMapping("/executeSqlScript/{serviceId}")
    private R executeSqlScript(@PathVariable String serviceId ,@RequestParam List<String> databases, @RequestBody String script){
        OrmDataSource dataSource = dataSourceCache.getDataSource(serviceId);
        AssertUtil.nullError(dataSource , "资源不存在" );
        DataSource source = DBServiceUtil.createDs(dataSource);
        ScriptRunner runner = null ;
        try{
            runner = new ScriptRunner(source.getConnection()) ;
            for (String database : databases) {
                GenericTokenParser tokenParser = new GenericTokenParser("#{","}",key->database);
                String executeSql = tokenParser.parse(script);
                runner.runScript(new StringReader(executeSql));
            }
            return R.ok() ;
        }catch (Exception e){
            return R.error(e.getMessage()) ;
        }finally {
            runner.closeConnection();
        }

    }
}
